FRACTAL LAB KIT IFS mappings module Ronald T. Kneusel May 25, 1993 version 1.0 Table of Contents I. Introduction What is this all about?................................. 3 Fractals and IFS (Iterated Function System)............. 5 Getting started......................................... 10 II. Tutorial A sample session........................................ 11 Using preset fractal maps............................... 12 Using basic commands.................................... 12 Using the FindMap command, an example.................. 15 III. Advanced features A very brief introduction to programming in Forth....... 16 An example : the Sierpinski Triangle.................. 19 Basic Forth words....................................... 21 IV. Reference Commands................................................ 22 Primitive words......................................... 25 Introduction What is this all about? The fractal lab kit is a command driven system for generating and investigating fractal images. It is written using Chris Heilman's Pocket Forth , a small Forth interpreter for the Macintosh. Pocket Forth is available via anonymous FTP from archive.umich.edu in the directory /mac/development/languages/. The kit consists of a set of Forth words that allow the user to easily create fractals based on IFS mappings. Because of it's small size and generality, it should run on virtually all Macintosh computers. By entering simple commands the user can define maps, draw the resultant fractals in a variety of colors, show the orientation of the mappings, measure positions within the image, and zoom in to view details. Fractals using up to 12 maps can be generated. Why not create a standard Macintosh application for all of this? I used Forth for two reasons. First, I am still learning the language and thought that this would be a good project towards that end. Secondly, I have used several fractal programs in the past and while they are excellent at what they do, they are rigid and inflexible. Creating a system like this in Forth seemed ideal. Forth is fast and highly interactive. It is also small and very easily extended. Not only does the user have all the fractal commands, but they also have all of Forth still at their disposal. A little programming can quickly extend the existing capabilities. Pocket Forth was my choice for several reasons, primarily, it is free and can be freely distributed, as well as supporting floating point numbers to make life easier. Fractal Lab Kit is freeware, if you use it and have any suggestions or comments please let me know at the addresses below. I have plans for additional 'modules' for investigating Mandelbrot and Julia sets, biomorph images, and chaos in one and two dimensions. Your feedback will encourage me to continue. Even if you have no specific comment, let me know where you are so I can follow the program. I prefer postcards, but email is good too. Ron Kneusel 507 S. 92nd St. Milwaukee, WI 53214 USA kneusel@msupa.pa.msu.edu or rtk@herman.gem.valpo.edu Fractals and IFS: an overview A fractal is a geometric object with a non-integer dimension. We are used to thinking in terms of Euclidean geometry, that is, in terms of points, lines, areas (surfaces), and volumes (solids). Fractals do not easily fit in such a framework and are difficult to comprehend (at least for me). Common geometrical objects have integer dimensions: Object Dimension ------ ---------- point 0 (no length or width or depth) line 1 (length only, no width or depth) plane 2 (length and width) solid 3 (length, width and depth) but fractals have non-integer dimensions, like 0.63... etc. How can this be you say? Let's look at the simplest fractal of them all: the Cantor set. To create the Cantor set imagine a line of length 1. Now, remove the middle third of that line. Remove the middle third of the two remaining lines. Continue removing the middle third an infinite number of times. When you are finished the object you will be left with is a fractal with a dimension that is not 0 (it's not a point) but is less than 1 (a line from 0 to 1 would contain all points, clearly a cantor set does not) and it can be shown that the final dimension is ln2/ln3 = 0.6309297536..... ¥¥¥¥¥¥ Begin Aside: Derivation of the Cantor Set dimension One possible definition of dimension, the self-similar dimension, is the ratio of the natural log of the number of intervals N (in 1-d) of length § needed to completely cover the set to the natural log of the reciprocal of §, taken in the limit that §-->0. In the case of the Cantor set §=(1/3)^n where n is the "level" of the set. (Check: the second level has two sections of length 1/3 while the next level has four sections of length 1/9 = (1/3)^2) So the condition §-->0 becomes n-->° . Also, for the Cantor set the number of intervals to cover the set at the level n is N=2^n . (Check: at the second level there are 2^1 = 2 intervals, at the third level there are 2^2=4 intervals and so on.) So we write: lim lim D = n-->° ln N / ln (1/§) = n-->° ln (2^n) / ln ( 1/(1/3)^n) lim D = n-->° n ln 2 / n ln 3 = ln2 / ln3 = 0.6309297536..... ¥¥¥¥¥¥ End Aside The Cantor set, like other purely mathematical fractals, is completely self-similar. That is, it looks identical on different scales (actually it is independent of scale). Take a piece of paper (you do have scrap paper near the computer; don't you?) and draw the first few lines of the Cantor set, one below the other: ------------------------- -------- --------- --- --- --- --- etc. (Yours will undoubtedly look better than mine) If you look at what you have just drawn you will notice that if you magnify a lower level it will look like one above it, the entire set is made up of an infinite number of copies of itself. (Infinity shows up frequently when talking about fractals) As this is a one dimensional fractal it is not terribly interesting; the program draws two dimensional fractals where life is a little less boring. They are definitely odd, but fractals do turn up in many places in nature, the nautilus shell (see the SPIRAL), your lungs and circulatory system (see the TREE), etc. Some people even think that the distribution of matter in the universe is a fractal. What about fractals and chaos? Fractals are often mentioned in connection with chaotic behavior of dynamical systems. The link comes from the fact that the final attractor (a strange attractor) of a dissipative dynamical system is a fractal object. If you want to talk more about this, contact me at the above address. What is IFS? IFS (Iterated Function System) is the means by which the program generates images. It was developed by Michael Barnsley. IFS involves defining a number of maps that in some way determine what the final product will look like (more on that later). An initial point is chosen (the origin is nice) and iterated (i.e. put it in - get something out - put that something back in, etc.) . These are maps in the mathematical sense - roughly, a way of transforming a collection of points into another space or back into its own space as is the case here. The map used for each iteration is chosen at random based on the assigned probability, the higher the probability the more likely that map is chosen. After each iteration the resulting point is plotted. As this process is continued the fractal image is built. Changing the probability of a map can dramatically affect the resulting image, so it might take a bit to get the picture "just right". It should be noted that the IFS algorithm is the heart of new data compression techniques that can achieve compression ratios of up to 30:1. In mathematical terms, a 2 dimensional map can be most easily represented in matrix form. A matrix is similar to the two dimensional arrays used in many programming languages. If we have a starting point (x,y) and we want to find the transformed coordinates, (x',y'), we can write the transformation in this way: |x'| |a b| |x| |e| |y'| = |c d| |y| + |f| This is equivalent to writing two equations: x' = a*x + b*y + e y' = c*x + d*y + f The 2x2 matrix controls the reorientation of the initial coordinate system while the vector (e f) is an offset to a new origin point for the map. Finding the "magic" numbers for an IFS transformation By way of example, I will show how to find the matrix values that generate what has become known as the Mandelbrot Dragon. While the dragon is usually generated according to a prescription (like the Cantor set above) it can also be found using two mappings (i.e. two matrices). Recalling that a fractal is made up of an infinite number of copies of itself, we need only specify the "first" copy and the IFS algorithm will fill in the rest. Therefore, imagine a square from 0 to 1, this is the starting point as it were. We must transform the points from this square into a different square (or squares), where the number of transformations equals the number of "parts" that the fractal is made up of. The dragon is made up of two parts: a contracted 45 degree rotation of the coordinate axes and a contracted -45 degree rotation (with a flip). Perhaps the best way to imagine this is to picture an arrow: ____________\_ from 0 to 1, the head of the arrow is only a half head so we can see if there is a flip as well as a rotation and translation. After some thought we realize that we need something like the following to generate the dragon: Again take a piece of paper and draw a 2 inch arrow as above, the head of the arrow is on the right and the barb is pointing north. Now, draw another arrow from the left edge of the first going at a 45 degree angle until it intersects an imaginary line running north to south that passes through the midpoint of the first line. Draw the barb of this arrow on the left side of the right endpoint of this line. Finally, complete the triangle and draw the barb of this arrow on the left side and touching the head of the second arrow. When you are finished you will have something like this: Ê ( see the MacPaint file 'Dragon Picture' ) where the directions of the arrow heads are crudely indicated. Finally, complete each of the three squares determined by the arrows as one edge. Now comes the fun part, how do we change the drawing into the numbers for the maps? To find the maps we need to solve, for each map, two systems of three linear equations since there are six numbers to find. To write the six equations we must know where at least three points of the original square (the one from 0 to 1) map to in the new maps. This is where the arrow head directions become important. The arrow determines two points for us, the head and the tail, while the last point can be either of the two corners of the original square and where they map to in the final square. So, to this end, label the tail and head of the first arrow drawn (a1,a2) and (b1,b2) respectively, and label the corner of the square above (a1,a2) as (c1,c2). These are the original three points, now label the corresponding points in the second square (the one at a positive 45 degree angle to the first) as (A1,A2) for the tail (in this case they are the same point) and (B1,B2) for the head. Label the farthest left corner of the square (C1,C2). Once this is done, we can write the following six equations to determine the first map: a1*a + a2*b + e = A1 b1*a + b2*b + e = B1 c1*a + c2*b + e = C1 and a1*c + a2*d + f = A2 b1*c + b2*d + f = B2 c1*c + c2*d + f = C2 In order to get actual numbers, we need to impose a coordinate system. Draw an x and y axis where the first arrow goes from 0 to 1 on the x axis and left edge of the first square goes from 0 to 1 on the y axis. In this coordinate system, (a1,a2)=(0,0); (b1,b2)=(1,0); (c1,c2)=(0,1) and the points for the first map are (A1,A2)=(0,0); (B1,B2)=(0.5,0.5); (C1,C2)= (-0.5,0.5). The values for the matrix and vector are found by solving the two systems. Cramer's Rule allows the solutions to be written as: |A1 a2 1| |a1 A1 1| |a1 a2 A1| |B1 b2 1| |b1 B1 1| |b1 b2 B1| |C1 c2 1| |c1 C1 1| |c1 c2 C1| a = --------- b = --------- e = ---------- |a1 a2 1| |a1 a2 1| |a1 a2 1 | |b1 b2 1| |b1 b2 1| |b1 b2 1 | |c1 c2 1| |c1 c2 1| |c1 c2 1 | Where the vertical lines represent the determinant (not the matrix as I have been using them for previously) and with a corresponding set for the c, d, and f values. With these we find that the first transformation is: |x'| |0.5 -0.5| |x| |0| |y'| = |0.5 0.5| |y| + |0| and applying the above to the second map gives: |x'| |-0.5 -0.5| |x| |1| |y'| = | 0.5 -0.5| |y| + |0| (I will leave the actual solution as an exercise.....) The last thing to consider is what sort of probability we want to assign to each of these maps. Since there is no reason to favor one map to another we can in this case get away with a probability of 0.5 for each (remember, probabilities should add to 1). This is not always the case, though. There are many good books on fractals and chaos at all levels, check the local book store or library. The book "Chaos: The Making of a New Science" by John Gleick is a good place to start, though it is lean on the technical aspects. Getting Started The IFS module includes a few different files. Double click the file Fractal Lab Kit to get things going. It contains the core IFS words. The file IFS-Maps contains about a dozen predefined fractal maps that will illustrate much of the versatility that can be obtained. (Thanks to Dr. Dale Snider, UW-Milwaukee Dept. of Physics, for the maps). Use Open under the File menu to load the maps. Enter the command PRESET to choose a map. The commands you enter are really just Forth words. In fact, you are really using Pocket Forth with the IFS words already defined, however, you need not be familiar with Forth to use the program. Tutorial A Sample Session In this sample session and what follows, things the user types are indicated in bold while the computer's response is in plain text. ok _open ok _fern green color on outlines draw ok _mouse ok _settings Current plot origin ( 0.00000 , 0.00000 ) Current screen origin ( 100 , 330 ) Current x & y scale is 1.0000 : 1.0000 Axes are currently OFF Draw Outlines is currently ON Current number of maps = 5 ok _off outlines 0.178 0.034 origin .25 range cdraw ok _bye Using the Preset Fractal Maps The file IFS-Maps contains code for about a dozen fractals. Use the word open or Open from the File menu to load the file. The command preset will bring a menu allowing the user to choose a particular fractal. Once the maps are loaded, the fractal can be generated by typing draw. All of the preset fractals should appear well centered on the screen, though to see all of the tree enter 250 330 screen draw to adjust the screen origin so that the entire image will fit, then enter reset to restore the default settings. At present, there is no way to store or print the images other than the open-apple-shift-3 command. They can then be loaded into TeachText and from there to any paint type program. Basic Commands A list of the basic, and most interactive, commands are presented along with an example of their use. These are the minimum commands necessary to use the program: draw Draw a fractal based on the current maps. Press a key to stop. E.g. green color fern draw cdraw Except for plotting each map in a different color, it is the same as draw. E.g. spiral cdraw edit Edit the n-th map. Enter a new value or press return to leave the existing value as is. E.g. 2 edit a = 0.5 ?-0.5 (new value) b = -0.5 ? etc. zero-maps Erase all twelve maps. E.g. zero-maps color Set the current drawing color to the color named. Valid colors are black, wite, red, green, blue, yellow, cyan, magenta E.g. magenta color maps Set the number of maps to use to . E.g. 4 maps origin Set the origin to (x,y). X and Y are floating point numbers. E.g. -0.354 .789 origin screen Set the screen origin to (u,v) (pixels). E.g. 120 220 screen range Set the range to (floating point). The viewing window is a square with the lower left corner as the origin and side length as range. E.g. 0.5 range scale Set the x-axis and y-axis scales to the floating point values given. The default scale is 1.0 for a full screen image. Changing the scale to a value less than one shrinks the image, greater than one expands the image. E.g. 2.0 2.0 scale mouse When issued, mouse will translate the position of the pointer into an x,y coordinate allowing the user to 'see' where certain parts of the image are. Clicking the mouse button between two points will measure the distance between them. Press a key to exit. on|off axes Turn the coordinate axes (really a mark on the origin) ON or OFF. E.g. off axes on|off outlines Set showing the map outlines on or off, press a key to continue after viewing the outlines. E.g. on outlines settings Show a list of the current origin, screen origin, range, scale, number of maps and whether the axes and outlines are on or off. E.g. settings findmap Allows the user to enter three initial coordinates and three image coordinates and calculates the map for those values. E.g. findmap make Puts the most recent values from findmap on the stack in order for set. The user needs to add the probability and map number before calling set. E.g. make .333 1 set

set Sets the parameters for a map. The letters a-f correspond to the values for the matrix and offset vector,

set Sets the parameters for a map. The letters a-f correspond to the values for the matrix and offset vector,

is the probability for the map and is the map number. All values except are to be floating point numbers. E.g. 0.5 -0.5 0.5 0.5 0.0 0.0 0.5 1 set copy Copy map number to without disturbing . E.g. 2 5 copy delete Delete map number and move any other maps up in memory. E.g. 3 delete insert Insert a blank map before map . E.g. 1 insert cls Clear the window. E.g. cls bye Exit Fractal Lab Kit. E.g. bye <9|12|13> monitor Set the program for a 9, 12, or 13 inch monitor. E.g. 13 monitor mem Show the available dictionary space. (Forth only has 32k) E.g. mem ?origin, ?screen, ?scale, ?range, ?maps, ?axes, ?outline, ?clear Show individual settings. settings calls each of these. show Show the values of map . E.g. 3 show Primitive commands These commands (words) are 'primitive' in the sense that they are called by the regular command words. Since they are standard Forth words they are available for user use as well. input ( -- a ) Get a 16-bit integer on the stack. finput ( -- f b ) Get a floating point number on the stack and a boolean value that is true if the user pressed the return key only, in which case the number is 0.0. #map->addr ( a -- addr ) Convert a number for a map into an address to the map location in memory. get ( offset map# -- value ) Get a value for a particular map. The offset is a branch into the map, each value is 10 bytes long. The constants a,b,c,d,e,f and p are defined to give the proper offset: c 3 get returns the c value of the third map. update ( value offset map# -- ) Put the value in the numbered map at the offset (use a-f or p). print ( addr -- ) Print the map starting at addr. wsize ( h v -- ) Resize the window to h pixels high and v pixels across. rand ( -- f ) Put a random floating point number from 0..1 on the stack. dot ( u v -- ) Draw a dot on the screen at (u,v) (pixels). plot ( x. y. -- ) Plot the point (x,y) on the screen. plotto ( x. y. -- ) Draw a line from the last plotted point to (x,y). determinant ( -- d ) Find the determinant of the 3x3 matrix whose values are stored in the floating point variables d1 through d9. Values in the form: [ [d1,d2,d3],[d4,d5,d6].[d7,d8,d9]]. x->d ( -- ) Copy the values in x1,y1 .. x3,y3 to the matrix d. Used to setup for finding a map. xy->uv ( x. y. -- u v ) Change real coordinates (x,y) into screen coordinates (u,v). Call factor first. factor ( -- ) Calculates redundant factors for xy->uv to speed drawing. firstpoints ( -- ) Get the initial points for a map, interactive. solve3x3 ( -- f. d. c. e. b. a. ) Solve for a map, calculated values on stack. Call either firstpoints and imagepoints or initial and image before calling solve3x3. outputmap ( f. d. c. e. b. a. -- ) Display map values on the stack on the screen.

is the probability for the map and is the map number. All values except are to be floating point numbers. E.g. 0.5 -0.5 0.5 0.5 0.0 0.0 0.5 1 set copy Copy map number to without disturbing . E.g. 2 5 copy delete Delete map number and move any other maps up in memory. E.g. 3 delete insert Insert a blank map before map . E.g. 1 insert cls Clear the window. E.g. cls bye Exit Fractal Lab Kit. E.g. bye Using the FindMap command : an example The FindMap command is perhaps the most useful command. It allows the user to find the parameters for a map by entering the coordinates and where they map to. This example will use the FindMap command to calculate the maps to find the Mandelbrot dragon which was introduced above. With in the program enter findmap. You will see be asked to enter the coordinates of three points from the original map. The origin, the lower right and upper left corners of the initial box (remember, it goes from 0..1 in both x and y) make good starting places. Therefore, enter 0 for x1 and 0 for y1, (1,0) for (x2,y2), and (0,1) for (x3,y3). You do not need to enter a decimal point with each number in this case, you can also press return to use the previously set value if desired (though it is not shown). For the image points, enter (x1',y1') as (0,0), (x2',y2') as (0.5,0.5) and (x3',y3') as (-0.5,0.5). The program will calculate the appropriate map and display its values. At the prompt, enter make 0.5 1 set to make this newly calculated map the first map. Enter findmap again and press return for each of the original points since we will use the same ones as before. For the image points enter (x1',y1') as (1,0), (x2',y2') as (0.5,0.5) and (x3',y3') as (0.5,-0.5). Then enter make 0.5 2 set to fix this as the second map. Lastly, enter 2 maps 120 220 screen cdraw to use two maps, adjust the screen origin so the image will fit, and draw using color. Advanced Features A very (very) brief introduction to programming in Forth Forth is an interpreted, stack based programming language known for its speed and extensibility. This is not an attempt to completely teach Forth so much as to teach a little about Forth so that the user who is unfamiliar with Forth can make some use of the language. Forth is a stack based language, data is manipulated using a stack that works in a way very similar to the lunch trays in a cafeteria. The last tray in the stack is the first one out. Because of this, all mathematical operations are in postfix format, i.e., instead of typing 4 + 7 one would type 4 7 + which would leave the value 11 on the top of the stack. This illustrates an important thing to remember about using Forth, anything that is entered is interpreted as either a word in the dictionary (more on that later) or a number to be pushed on the stack, so entering 4 7 + told Forth to push a 4 on the stack followed by a 7 and the + word adds the top two stack items. To see the value stored on the top of the stack use the . word. Note that this is a destructive operation, it prints the value at the top of the stack and removes it from the stack as well. To see the top stack value but NOT remove it you need to enter dup . to first duplicate the top item and then print it. By default, Forth only operates on 16-bit integers but Pocket Forth supports real numbers as well. Forth will interpret a value as a real number ONLY if it contains a decimal point! It is therefore important to enter a decimal point for every number that should be a real number and to NOT use one on numbers that should be integers. Forth supports the standard arithmetic operations: +, -, *, / (integers) and f+, f-, f*, f/ (real numbers). Use f. to print the top of stack as a real number. fdup duplicates the real number at the top of the stack while fswap will switch the top two real numbers on the stack. These few words will allow for using Forth as a simple calculator. Forth does not support higher mathematical functions. Forth derives its extensibility from the way in which programs are written. As Forth interprets tokens from the input line (anything surrounded by spaces is a token) it either pushes it on the stack as a number or looks it up as a word in its dictionary. A Forth program, therefore, consists of adding definitions to the dictionary. Definitions are begin with the : word and end with a semi-colon. Once defined, the word can be used in subsequent definitions. Parameters are passed via the stack. Forth does allow for the use of variables and constants, though these are slower than the stack. Use the word variable (or fvariable) followed by the name for the variable to create one. Use constant ( or fconstant) do define a constant. Examples: typing fvariable stddev will create room in the dictionary for a floating point variable named stddev while typing 3.141592 fconstant PI will create a constant for pi. Constants are really special words that push the value on the stack so that typing pi will cause the value to be pushed on the stack. However, entering the name of a variable will NOT place its value on the stack, but rather, the address where the variable is stored will be placed on the stack. To get the value of a variable a two word combination must be used: stddev f@ will 'fetch' a floating point number stored at the address that stddev places on the stack. Similarly, the value of an integer variable is found using @ instead of f@. To store a value in a variable, use ! or f! : 3 age ! or 1.414 sqr2 f!. Forth uses several standard control structures: if else then, do loop (or +loop), begin until, begin while repeat. The phrase count @ 100 < if ." Yes, there is room" cr else ." No, there is no room." cr then will check whether the current value of count is less than 100 or not. Forth supports <, >, = for comparing integer values. Pocket Forth has a single word for comparing floating point numbers, fcompare, which returns a -1 if f1f2, where f1 and f2 are the top two stack numbers (assumed to be floating point). It is important to note that unlike most other Forth words, fcompare does not remove the top two floating point numbers. The do loop is similar to the for loops in other languages. As might be expected, the syntax is do loop where the index (pushed on the stack by the word r) will go from to -1. A variation is to use +loop instead of loop to jump by the value on the top of the stack (which must be positive). Begin until and begin while repeat are for bottom tested and top tested conditional loops. The condition is the same as for the if statement: 0 begin ." Hello" cr 1+ dup 100 < until will print the word 'Hello' 100 times. Similarly, this fragment will also print 'Hello' 100 times: 0 begin dup 99 < while ." Hello" cr 1+ repeat Putting it all together The following examples will illustrate the creation of simple Forth words, after which an example using fractal generating words will be presented. 1. Averaging four numbers : ave4 ( a b c d -- average ) + + + 4 / ; Using integer arithmetic, sum the top four stack items and divide the result by 4. Illustrates comments which are anything surrounded by (), note the space after the (. The comment given is known as a stack effect comment and shows what effect the word has on the stack. Initial stack items are on the left of the -- and the result is on the right. 2. Averaging N floating point numbers : averageN ( a1. ... aN. N -- average. ) dup >r ( save N on the return stack ) 1- 0 do ( adjust N and add the values ) f+ loop r> ( get N off the return stack ) 0 d>f f/ ; ( make it real and divide to find average ) This example illustrates use of the return stack. The return stack is the place where Forth places addresses to return to when the current word is done executing. While a word is executing it is possible to use the return stack for temporary storage, but one must be careful to make sure that all values placed on the stack by >r are removed using r> before the word is done, otherwise Forth will attempt to return to ??? and very likely crash. The way to convert an integer to a real number is to use the words 0 d>f. This transforms the integer into a double length integer and then into a real number. 3. Evaluating a function: Y = 3.4 * EXP (X^2) fvariable x : sqr ( x. -- x.*x. ) fdup f* ; : cube ( x. -- x.^3 ) fdup fdup f* f* ; : expf ( x. -- exp[x.] ) ( use Taylor series approx. ) fdup x f! 1.0 f+ x f@ sqr 2.0 f/ f+ x f@ cube 6.0 f/ f+ ; : Y ( x. -- Y[x.] ) expf 3.4 f* ; This is an example of factoring: the code for the square and cube could easily have been left in the definition of expf but factoring them out made the definition shorter and easier to read. In theory, according to some, a properly factored Forth program, combined with well chosen word names and stack effect comment, should be nearly self-documenting. These examples are brief, but hopefully should be sufficient, especially when combined with a list of Forth words, to allow writing of simple words to extend the power of the program. The Sierpinski Triangle : an example The Sierpinski Triangle is a commonly seen fractal consisting of a triangle that is made up of triangles. This will serve as an example of how the program can be extended by adding words to the Forth dictionary. The triangle is made up of three maps that divide the region 0..1 in x and 0..1 in y into three equal squares. We will develop a Forth word that will find the maps for the triangle and then generate the fractal. First, we must determine the maps. The findmap command's interactive nature is unsuited to our task, fortunately, there are three 'primitive' (i.e. non-interactive) words that will perform the same task: initial, image, and solve. These words operate as follows: initial Sets the initial points for finding a map, (x1,y1),(x2,y2),(x3,y3). image Sets the image points for finding a map, (X1,Y1),(X2,Y2),(X3,Y3). solve Finds the values that will map the initial points to the image points. These words, when combined with make and set, will allow us to create a single Forth word to find all three maps at once. At this point, then, we can write: : sierpinski ( generates the Sierpinski Triangle) ( Set up initial values, for all maps ) 0.0 0.0 1.0 0.0 0.0 1.0 initial ( First map ) 0.0 0.0 0.5 0.0 0.0 0.5 image solve make 0.333 1 set ( Second map ) 0.5 0.0 1.0 0.0 0.5 0.5 image solve make 0.333 2 set ( Third map ) 0.25 0.5 0.75 0.5 0.25 1.0 image solve make 0.333 3 set Now before viewing the fractal show the maps, reset the program and show the settings, and draw the outlines: ( Show the maps ) page ." The Sierpinski maps: " cr showmaps reset settings key drop ( wait for a key press ) ( Show outlines when drawing ) on outlines ( Reset the program and draw the fractal ) cdraw ; Try this word and see what happens. Basic Forth words Below is a list of some basic Forth words and their use. With these it should be possible to define your own words for use with the program. Word Use swap ( a b -- b a ) Switch top two stack items dup ( a -- a a ) Duplicate top of stack over ( a b -- a b a ) Bring 2nd to top rot ( a b c -- b c a ) Rotate stack items variable ( -- ) Make a variable of next token constant ( a -- ) Make a constant of next token +, -, *, / ( a b -- a$b ) Math, where $ is an operation mod ( a b -- a mod b ) Remainder after dividing drop ( a -- ) Drop the top stack item cr ( -- ) Print a return character space ( -- ) Print a space (ASCII 32) emit ( a -- ) Print the character whose code is on the stack ." ( -- ) Print text until a " found . ( a -- ) Print the top of stack key ( -- a ) Get a key, ASCII code on stack bye ( -- ) Exit from Forth open ( -- ) Load a file from disk ?terminal ( -- b ) Has a key been pressed? ( ( -- ) Start a comment (remember space) !pen ( x y -- ) Move the pen to (x,y) (pixels) -to ( x y -- ) Line from current to (x,y) page ( -- ) Clear the screen --> ( -- ) Load filename, no spaces! open ( -- ) Load file chosen in Mac dialog ?button ( -- t ) Mouse button down? @mouse ( -- x y ) Push mouse position on stack save ( -- ) Save the current dictionary. This is PERMANANT! Only use a copy! Once saved, the words you defined will be available immediately when the program is next run. See the reference section for more words that are program specific. Words in plain text are special to Pocket Forth and may not be available on other Forth systems, though there will likely be something like them. Those interested in seriously learning Forth (some swear that it is the best computer language there is) should get a hold of the book Starting Forth by Leo Brodie (2nd ed. 1987), it is an excellent introduction. Reference Commands draw Draw a fractal based on the current maps. Press a key to stop. E.g. green color fern draw cdraw Except for plotting each map in a different color, it is the same as draw. E.g. spiral cdraw idraw or icdraw Same as draw and cdraw respectively except for iterating through *500 points. Useful for drawing a fractal and stopping without user interaction. edit Edit the n-th map. Enter a new value or press return to leave the existing value as is. E.g. 2 edit a = 0.5 ?-0.5 (new value) b = -0.5 ? etc. zero-maps Erase all twelve maps. E.g. zero-maps color Set the current drawing color to the color named. Valid colors are black, wite, red, green, blue, yellow, cyan, magenta E.g. magenta color maps Set the number of maps to use to . E.g. 4 maps origin Set the origin to (x,y). X and Y are floating point numbers. E.g. -0.354 .789 origin screen Set the screen origin to (u,v) (pixels). E.g. 120 220 screen range Set the range to (floating point). The viewing window is a square with the lower left corner as the origin and side length as range. E.g. 0.5 range scale Set the x-axis and y-axis scales to the floating point values given. The default scale is 1.0 for a full screen image. Changing the scale to a value less than one shrinks the image, greater than one expands the image. E.g. 2.0 2.0 scale mouse When issued, mouse will translate the position of the pointer into an x,y coordinate allowing the user to 'see' where certain parts of the image are. Clicking the mouse button between two points will measure the distance between them. Press a key to exit. on|off clear Turn clearing of page before drawing on and off. Default is on. on|off axes Turn the coordinate axes (really a mark on the origin) ON or OFF. E.g. off axes on|off outlines Set showing the map outlines on or off, press a key to continue after viewing the outlines. E.g. on outlines settings Show a list of the current origin, screen origin, range, scale, number of maps and whether the axes and outlines are on or off. E.g. settings findmap Allows the user to enter three initial coordinates and three image coordinates and calculates the map for those values. E.g. findmap make Puts the most recent values from findmap on the stack in order for set. The user needs to add the probability and map number before calling set. E.g. make .333 1 set